Skip to content

一、概述

在Tair出现之前的很长一段时间里,像redis、memcache这些知名NoSql数据库是不支持分布式的,在这样的背景下,由淘宝网自主开发并在2010.6开源的一个高性能、高扩展、高可靠分布式缓存,类似map的key/value结构,在淘宝、天猫等各个应用中广泛应用。

Tair官网 gitee地址 github wiki地址

特性 Tair实现了集群部署,特性都是一些集群的特性,容错、解决单点故障、跨机房管理、多集群管理、支持副本等。Tair的特性有: • Namespace • Expire • Prefix • List,zset,hash,set • LocalCache • FlowControl 抽象存储层,内部采用MDB、RDB、LDB三中存储引擎满足了各种存储需求。 MDB是内存型,K/V结构,底层是memcache ,由于是内存型性能最高但是不支持持久化。 RDB底层是redis引擎,支持List、Set、Zset、Map、String等多种数据结构,性能略低于MDB。 LDB是持久化型引擎,底层是google的levelDB,K/V结构,性能最低,但是可靠性最高。 应用场景 由于Tair底层的MDB、RDB、LDB三种引擎支持,既能作为缓存使用又可以作为持久化存储数据库,命令除了put、get、delete以及批量接口外,还有一些附加的实用功能比如version支持、原子计数器、item支持,可以用于实现分布式锁,队列等。

1.1 相关概念

  • configID:一个Tair集群的唯一标识
  • namespace:应用的一个内存或者持久化存储区域,0到65535之间的一个数字
  • quta:配额,对应了每个 namespace 储存区的大小限制,超过配额后将使用LRU(最少使用)策略淘汰
  • expireTime:数据的过期时间。当超过过期时间之后,数据将对应用不可见,不同的存储引擎有不同的策略清理掉过期的数据
  • prefix:前缀处理,保证了拥有相同前缀的key根据哈希算法后,分散在同一个dataserver上,提高了处理速度。

1.2 version支持

​ 在Tair的put接口中,有一个version参数,这个参数是为了解决并发更新同一个数据而设置的。很多情况下,更新数据是先get,修改get回来的数据,然后put回系统。如果有多个客户端get到同一份数据,都对其修改并保存,那么先保存的修改就会被后到达的修改覆盖,从而导致数据丢失问题。 ​ 比如,缓存中有一个value值为 “a,b,c”,A和B同时get到这个value。A执行操作,在后面添加一个d,value为 “a,b,c,d”。B执行操作添加一个e,value为”a,b,c,e”。如果不加控制,无论A和B谁先更新成功,它的更新都可能会被后到的更新覆盖。

version使用方式

​ get接口返回的是DataEntry对象,该对象中包含get到的数据的版本号,可以通过getVersion()接口获得该版本号。在put时,将该版本号作为put的参数即可。 如果不考虑版本问题,则可设置version参数为0,系统将强行覆盖数据,即使版本不一致。

如果返回version不一致,怎么办?

​ 如果更新所基于的version和系统中当前的版本不一致,则服务器会返回ResultCode.VERERROR。 这时你可以选择重新get数据,然后在新版本的数据上修改;或者设置version为0重新请求,以达到强制更新的效果。

1.3 Tair使用规范

key和value不能设置太大,否则耗时大,服务qps(每秒查询率)低,影响性能 key不要使用相同的值作为前缀,否则数据都会落到一个dataserver上,增加该数据节点的压力 批量请求的key个数不要太大,否则也会影响性能 超时时间也不要设置太大或者太小,设置太小容易超时,设置太大容易阻塞,建议使用默认值 Tair虽然支持list,set,map等复杂数据结构,但是支持不是很好,元素个数不易过多

二、使用示例

2.1 入门Demo

依赖

xml
 <dependency>
     <groupId>com.taobao.tair</groupId>
     <artifactId>tair-client</artifactId>
     <version>2.3.5</version>
 </dependency>
 <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.59</version>
 </dependency>

测试使用

java
package com.itheima;

import com.alibaba.fastjson.JSON;
import com.taobao.tair.DataEntry;
import com.taobao.tair.Result;
import com.taobao.tair.impl.DefaultTairManager;

import java.util.ArrayList;
import java.util.List;

public class TestTair {
    public static void main(String[] args) {
        List<String> configList = new ArrayList<String>();
        configList.add("192.168.31.97:5198");//ConfigServer的ip和端口
        DefaultTairManager tairManager = new DefaultTairManager();
        tairManager.setConfigServerList(configList);
        tairManager.setGroupName("group_test");//和配置中的组名称保持一致
        tairManager.init();

        ResultCode putResult = tairManager.put(1, "name", "itcast");
        System.out.println(JSON.toJSONString(putResult));
        //{"code":0,"message":"success","success":true}
        
        Result<DataEntry> getResult = tairManager.get(1, "name");
        System.out.println(JSON.toJSONString(getResult));	
        //{"rc":{"code":0,"message":"success","success":true},"success":true,"value":{"createDate":0,"expriedDate":0,"key":"name","locked":false,"modifyDate":1585119311,"value":"itcast","version":1}}
        
        System.out.println(getResult.getValue());
		//value: key: name, value: itcast, version: 1 cdate: 1970-01-01 08:00:00 mdate: 2020-03-25 02:55:11 edate: NEVER
        
		System.out.println(getResult.getValue().getValue());
		//itcast
    }
}

三、核心知识

3.1 主要方法

put

put重载了三个方法,namespace是存储空间,0到65535之间,key和value都会序列化,version是版本号,expireTime是失效时间,单位为秒

java
ResultCode put(int namespace, Serializable key, Serializable value)
ResultCode put(int namespace, Serializable key, Serializable value, int version)
ResultCode put(int namespace, Serializable key, Serializable value, int version, int expireTime)

get

get接口用于获取单个数据,要获取的数据由namespace和key指定。 当数据存在时,返回成功,数据存放在DataEntry对象中; 当数据不存在时,返回成功,ResultCode为ResultCode.DATANOTEXSITS,value为null。

java
Result<DataEntry> get(int namespace, Serializable key)

mget

mget接口用于批量获取数据,要获取的数据由namespace和keys 集合指定。 数据存放在DataEntry对象中病放到List中返回

java
Result<List<DataEntry>> mget(int namespace, List<? extends Object> keys)

delete

根据namespace和key删除指定缓存

java
ResultCode delete(int namespace, Serializable key)

mdelete

根据namespace和 keys 批量删除

java
ResultCode mdelete(int namespace, List<? extends Object> keys)

getStat

得到统计信息

java
Map<String,String> getStat(int qtype, String groupName, long serverId)

incr/decr

namespace:计数器所在的namespace,key:缓存的key,value:本次增加 或者 减少值,defaultValue: 当计数器不存在时的初始化值 ,expireTime:过期时间,单位为秒

java
Result<Integer> incr(int namespace, Serializable key, int value,
								int defaultValue, int expireTime)
Result<Integer> decr(int namespace, Serializable key, int value,
							int defaultValue, int expireTime)

setCount

将key对应的计数设置成count,忽略key原来是否存在以及是否是计数类型。因为Tair中计数的数据有特别标志,所以不能直接使用put设置计数值。

java
ResultCode setCount(int namespace, Serializable key, int count)
ResultCode setCount(int namespace, Serializable key, int count, int version, int expireTime)

lock/unlock

在并发情况下可以通过lock和unlock来实现分布式锁

java
ResultCode lock(int namespace, Serializable key)
ResultCode unlock(int namespace, Serializable key)

invalid/minvalid

删除缓存

java
ResultCode invalid(int namespace, Serializable key)
ResultCode minvalid(int namespace, List<? extends Object> keys)

3.2 架构组件

一个Tair集群主要包括3个必选模块:ConfigServerDataserverClient

通常情况下,一个 Tair 集群中包含2台 Configserver 及多台 DataServer。其中两台 Configserver 互为主备。通过和 Dataserver 之间的心跳检测获取集群中存活可用的 Dataserver,构建数据在集群中的分布信息(对照表)。Dataserver 负责数据的存储,并按照 Configserver 的指示完成数据的复制和迁移工作。Client 在启动的时候,从 Configserver 获取数据分布信息,根据数据分布信息,和相应的 Dataserver 进行交互,完成用户的请求。

从架构上看,Configserver 的角色类似于传统应用系统的中心节点,整个集群服务依赖于 Configserver 的正常工作。而实际上,Tair 的 Configserver 是非常轻量级的,当正在工作的 Configserver 宕机的时候,另一台会在秒级别时间内自动接管。而且,即使出现两台 ConfigServer 同时宕机的恶劣情况,只要 DataServer 没有新的变化,Tair 依然服务正常。应用在使用时只需要连接 Configserver,而不需要知道内部节点的情况。

table

对照表,存放了桶和dataserver的对应关系,put数据时,会对key进行hash计算,在对桶数量取模,然后根据对照表找到相应的dataserver

Client

  • 提供访问 Tair 集群的API
  • 更新并缓存数据分布表
  • LocalCache,避免过热的数据访问影响 Tair 集群服务。
  • 流量控制

common

common 目录提供基础数据结构和组件

ConfigServer

  • 两台 Configserver 互为主备
  • 通过和 Dataserver 之间的心跳检测来获取集群中存活、可用的 Dataserver 节点信息
  • 根据获取的 Dataserver 节点信息构建数据在集群中的分布表
  • 提供数据分布表的查询服务
  • 调度 Dataserver 之间的数据迁移、复制

DataServer

  • 提供存储引擎
  • 接受 Client 发起的 put/get/remove 等操作
  • 执行数据迁移、复制
  • 访问统计

Storage

Tair的存储分为两种:persistence(持久化)和 cache(非持久化) ,非持久化Tair看成是分布式缓存,持久化Tair将数据序列化到磁盘,还可以配置备份数量,将一份数据放到不同的主机上,防止数据丢失。 ​ Tair对存储做了一个抽象层,可以很方便的替换 tair 底层的存储引擎,主要有下面三种存储引擎:

  • mdb 一个高效率的关系型缓存存储数据库,定位于 cache 缓存,类似于 memcache。采用page/slab管理内存。支持 k/v 存取、prefix 操作、expire数据过期,采用共享内存方式,重启数据不丢。阿里内部大都采用此种模式。 图中mempool是申请到的内存池,大小在配置文件dataserver.conf中指定slab_mem_size=4096,默认是4个g,mempool被划分很多slab组,每组slab下又包含了若干page,每个page下又包含了一组chunk,memcache中叫chunk在图中指定item,item是真正存放数据的地方。
  • rdb 定位于 cache 缓存,采用了 redis 的内存存储结构。支持 k/v, list, hash, set, sortedset 等数据结构。
  • ldb ldb,定位于高性能存储, 多实例配置使用,充分利用IO,采用了 levelDB 作为引擎,并可选择内嵌mdb作为KV级别cache 加速,这种情况下 cache 与持久化存储的数据一致性由 tair 进行维护。支持 k/v,prefix 等数据结构。 Memtable:内存数据结构,新的数据会首先写入这里。 Log文件:写Memtable前会先写Log文件,Log通过append的方式顺序写入,Log的存在使得机器宕机导致的内存数据丢失得以恢复。 compact:压缩,LevelDB的一个重要特性就是数据的分层,由于数据的分层, 越旧的数据处在越大的层级,越新的数据在越小的层级,compaction的过程是产生SSTable的过程,在查询数据的时候, 最先读取MemTable里面的数据, 然后是L0的SSTable里面, 接着是L1, L2直到最大的层级。在分层设计中, 越往上层,数据的容量越大, 大约Ln是Ln-1层数据的10倍。 在各个层级的SSTable文件, 只有L0层的数据是有MemTable直接flush到磁盘上, 其它层的数据是经过compaction过程进行排序整理产生的。这意味着L0层以上的数据, 各个SSTable文件内的数据是有序且不会重叠的。

packets

packets目录提供了通信协议中各种数据包的实现。基础库主要包括tbsys和tbnet,其中tbsys是主要的数据结构和文件操作的实现,包括排它锁和读写锁实现,对线程的包装,以及配置文件读写和分析等。tbnet是主要实现了单线程的网络读写数据流,采用了epoll的模式。

plugin

tair 还内置了一个插件容器,可以支持热插拔插件。插件由 config server 配置,config server 会将插件配置同步给各个数据节点,数据节点会负责加载/卸载相应的插件。

插件分为 request 和 response 两类,可以分别在 request 和 response 时执行相应的操作,比如在 put 前检查用户的 quota 信息等。插件容器也让 tair 在功能方便具有更好的灵活性。

四、安装

4.1 常规安装

安装相关依赖库

sh
# yum:是yellowdog updater modified 的缩写,Linux中的包管理工具


<NolebasePageProperties />




#gcc:一开始称为GNU C Compiler,也就是一个C编译器,后来因为这个项目里集成了更多其他不同语言的编译器,所以就不再只是C编译器,而称为GNU编译器套件(GCC,GNU Compiler Collection),表示一堆编译器的合集
# gcc-c++则是GCC编译器合集里的C++编译器。
#make是gcc的编译器,m4:是一个宏处理器.将输入拷贝到输出,用来引用文件,执行命令,整数运算,文本操作,循环等.既可以作为编译器的 前端,也可以单独作为一个宏处理器.
# libtool:是一个通用库支持脚本,作用是在编译大型软件的过程中解决了库的依赖问题;将繁重的库依赖关系的维护工作承担下来,提供统一的接口,隐藏了不同平台间库的名称的差异等。安装libtool会自动安装所依赖的automake和autoconfig, autoconf:是用来生成自动配置软件源代码脚本(configure)的工具.configure脚本能独立于autoconf运行, automake:会根据源码中的Makefile.am来自动生成Makefile.in文件,Makefile.am中定义了宏和目标,运行automake命令会生成Makefile文件,然后使用make命令编译代码。
# boost-devel zlib-devel openssl-devel libcurl-devel:都是编译时所依赖的库。
yum install -y gcc gcc-c++ make m4 libtool boost-devel zlib-devel openssl-devel libcurl-devel

下载源码

sh
# 由于Tair依赖tbsys和tbnet库,需要安装这两个库,而这两库需要编译tb-common-utils安装
# 安装git:
[root@test ~]# yum install -y git

# 从码云上下载tb-common-utils源码:
[root@test ~]# git clone https://gitee.com/abc0317/tb-common-utils.git
[root@test ~]# cd tb-common-utils/
[root@test tb-common-utils]# ll
    total 16
    -rwxrwxrwx. 1 root root  820 Mar 20 09:28 build.sh
    -rw-r--r--. 1 root root   79 Mar 20 09:28 README.md
    drwxr-xr-x. 5 root root 4096 Mar 20 09:34 tbnet
    drwxr-xr-x. 5 root root 4096 Mar 20 09:33 tbsys
# 赋予执行权限
[root@test tb-common-utils]# chmod u+x build.sh
# 指定TBLIB_ROOT环境变量 TBLIB_ROOT为需要安装的目录。
[root@test tb-common-utils]# export TBLIB_ROOT=/root/tairlib

# 进入源码目录, 执行build.sh进行安装
[root@test tb-common-utils]# sh build.sh



# 从码云上下载Tair源码:
[root@test tb-common-utils]#cd ~
[root@test ~]# git clone https://gitee.com/mirrors/Tair.git

编译安装

sh
[root@test ~]# cd Tair
# 编译依赖
[root@test Tair]# ./bootstrap.sh
# 检测和生成 Makefile (默认安装位置是 ~/tair_bin, 修改使用 --prefix=目标目录)
[root@test Tair]# ./configure
# 编译和安装到目标目录
[root@test Tair]# make -j && make install

配置 基于MDB内存引擎,采用最小化配置方式,1个ConfigServer,1个DataServer搭建Tair集群

由于MDB 引擎默认使用共享内存,所以需要查看并设置系统的tmpfs的大小,tmpfs是Linux/Unix系统上的一种基于内存的虚拟文件系统。

sh
# df命令用于显示目前在Linux系统上的文件系统的磁盘使用情况统计
[root@test Tair]# df -h

/dev/shm 目录位于 linux 系统的内存中,而不在磁盘里,所以它的效率非常高,这里我们将大小设置1G,

修改**/etc/fstab** 的这行,如果没有就在末尾加一行

tmpfs /dev/shm tmpfs defaults 0 0

改为

tmpfs /dev/shm tmpfs defaults,size=1G 0 0

改完之后,执行mount使其生效

mount -o remount /dev/shm

生效后再使用df -h 查看

shell
[root@test Tair]# df -h

切换到Tair安装目录,拷贝默认配置文件准备修改

shell
[root@test ~]# cd /root/tair_bin/etc
[root@test etc]# mv configserver.conf.default configserver.conf
[root@test etc]# mv group.conf.default group.conf
[root@test etc]# mv dataserver.conf.default dataserver.conf

该机器ip是 192.168.31.97 configserver.conf

makefile
# tair 2.3 --- configserver config
#
[public]
# 主备 ConfigServer 的地址和端口号,第一行为主,第二行为备,目前采用最简单集群只配置一个ConfigServer
#config_server=192.168.1.1:5198
#config_server=192.168.1.2:5198
config_server=192.168.31.97:5198






[configserver]
# ConfigServer 的工作端口号,和上面的配置以及 dataserver.conf 里的要一致
port=5198
# 日志文件位置
log_file=logs/config.log
# pid 存储的文件位置
pid_file=logs/config.pid
# 默认日志级别
log_level=warn
# group.conf 文件的位置
group_file=etc/group.conf
# 运行时状态持久化文件的位置
data_dir=data/data
# 使用的网卡设备名设置为你自己当前网络接口的名称,默认为eth0
dev_name=eth0

group.conf

makefile
#group name
# 集群分组的名字,tair 支持一组 ConfigServer 管理多个集群 (不建议,避免流量瓶颈在 ConfigServer 上)
#[group_1]
[group_test]






# data move is 1 means when some data serve down, the migrating will be start.
# default value is 0
# 是否允许数据迁移,双份数据情况下,要设置为 1 (内部逻辑判断是双份的话,内部也会强制置为1)
_data_move=0
#_min_data_server_count: when data servers left in a group less than this value, config server will stop serve for this group
#default value is copy count.
# 过载保护的参数,当可用的 DataServer 节点少于这个数字时,ConfigServer 不再自动检测宕机并重建路由表(避免逐台击穿而雪崩)
_min_data_server_count=1
#_plugIns_list=libStaticPlugIn.so
# 建表算法的选择和一些参数,一般默认即可
_build_strategy=1 #1 normal 2 rack
_build_diff_ratio=0.6 #how much difference is allowd between different rack
# diff_ratio =  |data_sever_count_in_rack1 - data_server_count_in_rack2| / max (data_sever_count_in_rack1, data_server_count_in_rack2)
# diff_ration must less than _build_diff_ratio
_pos_mask=65535  # 65535 is 0xffff  this will be used to gernerate rack info. 64 bit serverId & _pos_mask is the rack info,
# 数据的备份数,注意集群一旦初始化,不能修改这个值
_copy_count=1
# 虚拟节点的个数,当集群机器数量很多时,可以调整这个值
# 注意一旦集群初始化完毕,这个值不能修改
_bucket_number=1023
# accept ds strategy. 1 means accept ds automatically
# 该文件的修改会触发 ConfigServer 自动 reload,下面的参数控制是否自动加入本文件新增的 DataServer 节点到集群
# _min_data_server_count 参数也会影响,如果节点总数小于 _min_data_server_count,也不会自动加入
_accept_strategy=1
# 是否允许 failover 机制
# 这个机制工作在 LDB 引擎模式的集群下,当 _min_data_server_count 参数大于集群机器数(阻止自动剔除宕机机器)时,
# 如果该参数为1,宕机的第一个节点会进入 failover 模式,此时备机接管读写请求,同时记录恢复日志,当宕机节点恢复时,
# 自动进入 recovery 模式,根据恢复日志补全数据。注意此时第二台如果宕机,不会自动处理,所以第一台一旦宕机收到告警,
# 请尽快人为干预处理。  **failover 机制想正常工作,需要 dataserver.conf 的 do_dup_depot 为 1 才可以**
_allow_failover_server=0

# 下面是 DataServer 节点列表,注释 data center A/B 并不是集群组的概念
# 集群组的配置是当前这个文件所有内容,复制整个内容追加到本文件尾部,可以添加一个集群组
# 注意一个节点不能出现在两个集群组里!配置文件不做该校验。
# data center A
#_server_list=192.168.1.1:5191
#_server_list=192.168.1.2:5191
#_server_list=192.168.1.3:5191
#_server_list=192.168.1.4:5191
_server_list=192.168.31.97:5191






# data center B
#_server_list=192.168.2.1:5191
#_server_list=192.168.2.2:5191
#_server_list=192.168.2.3:5191
#_server_list=192.168.2.4:5191

#quota info
# 配额信息
# 当引擎是 MDB 时,控制每个 Namespace 的内存配额,单位是字节
# Tair 支持 0~65535 的 Namespace 范围,每个 Namespace 内部的 key 命名空间隔离
# 代码中出现的 area 是 Namespace 的同义词
_areaCapacity_list=0,1124000;

dataserver.conf

makefile
#
#  tair 2.3 --- tairserver config
#
[public]
# 主备 ConfigServer 的地址
#config_server=192.168.1.1:5198
#config_server=192.168.1.2:5198
config_server=192.168.31.97:5198





[tairserver]
#
#storage_engine:
#
# mdb
# ldb
#
# 使用的引擎,支持 MDB 和 LDB
storage_engine=mdb
local_mode=0
#
#mdb_type:
# mdb
# mdb_shm
#
# 如果引擎是 MDB,这里选择使用普通内存还是共享内存
mdb_type=mdb_shm

# shm file prefix, located in /dev/shm/, the leading '/' is must
# MDB 实例的命名前缀,一般在单机部署多个节点时需要修改
mdb_shm_path=/mdb_shm_inst
# (1<<mdb_inst_shift) would be the instance count
# MDB 引擎的实例个数,多个实例减少锁竞争但是会增加元数据而浪费内存
#mdb_inst_shift=3
mdb_inst_shift=0





# (1<<mdb_hash_bucket_shift) would be the overall bucket count of hashtable
# (1<<mdb_hash_bucket_shift) * 8 bytes memory would be allocated as hashtable
# MDB 实例内部 hash 表的 bucket 数,24~27均可(取决于实例大小)
mdb_hash_bucket_shift=24
# milliseconds, time of one round of the checking in mdb lasts before having a break
mdb_check_granularity=15
# increase this factor when the check thread of mdb incurs heavy load
# cpu load would be around 1/(1+mdb_check_granularity_factor)
mdb_check_granularity_factor=10

#tairserver listen port
port=5191

supported_admin=0
# 工作时的 IO 线程数和 Worker 线程数
#process_thread_num=12
process_thread_num=4





#io_thread_num=12
io_thread_num=4





# 双份数据时,往副本写数据的 IO 线程数,只能是 1
dup_io_thread_num=1
#
#mdb size in MB
#
# MDB 引擎使用的存储数据的内存池总大小 这里 slab_mem_size控制MDB内存池的总大小,mdb_inst_shift 控制实例的个数,每个实例的大小是 slab_mem_size/(1 << mdb_inst_shift) MB,注意这里一个实例必须大于512MB且小于64GB
#slab_mem_size=4096
slab_mem_size=512





log_file=logs/server.log
pid_file=logs/server.pid

is_namespace_load=1
is_flowcontrol_load=1
tair_admin_file = etc/admin.conf

# 是否在put操作遍历 hash 表冲突链时,顺带删除已经 expired 的数据
# 会导致 put 的时延增大一点点,但是有利于控制过期数据很多的场景下内存增幅
put_remove_expired=0
# set same number means to disable the memory merge, like 5-5
mem_merge_hour_range=5-5
# 1ms copy 300 items
mem_merge_move_count=300

log_level=warn
dev_name=eth0
ulog_dir=data/ulog
ulog_file_number=3
ulog_file_size=64
check_expired_hour_range=2-4
check_slab_hour_range=5-7
dup_sync=1
dup_timeout=500

# 是否使用 LDB 集群间的数据自动同步
do_rsync=0

rsync_io_thread_num=1
rsync_task_thread_num=4

rsync_listen=1
# 0 mean old version
# 1 mean new version
# 这里只能是 1
rsync_version=1
# 同步的详细配置地址,也可以使用 file:// 来指定本地磁盘的配置位置
rsync_config_service=http://localhost:8080/hangzhou/group_1
rsync_config_update_interval=60

# much resemble json format
# one local cluster config and one or multi remote cluster config.
# {local:[master_cs_addr,slave_cs_addr,group_name,timeout_ms,queue_limit],remote:[...],remote:[...]}
# rsync_conf={local:[10.0.0.1:5198,10.0.0.2:5198,group_local,2000,1000],remote:[10.0.1.1:5198,10.0.1.2:5198,group_remote,2000,800]}
# if same data can be updated in local and remote cluster, then we need care modify time to
# reserve latest update when do rsync to each other.
rsync_mtime_care=0
# rsync data directory(retry_log/fail_log..)
rsync_data_dir=./data/remote
# max log file size to record failed rsync data, rotate to a new file when over the limit
rsync_fail_log_size=30000000
# when doing retry,  size limit of retry log's memory use
rsync_retry_log_mem_size=100000000

# depot duplicate update when one server down
# failover 机制的 DataServer 开关,见 group.conf 相关说明
do_dup_depot=0
dup_depot_dir=./data/dupdepot

# 默认的流控配置,total 为整机限制
[flow_control]
# default flow control setting
default_net_upper = 30000000
default_net_lower = 15000000
default_ops_upper = 30000
default_ops_lower = 20000
default_total_net_upper = 75000000
default_total_net_lower = 65000000
default_total_ops_upper = 50000
default_total_ops_lower = 40000

[ldb]
#### ldb manager config
## data dir prefix, db path will be data/ldbxx, "xx" means db instance index.
## so if ldb_db_instance_count = 2, then leveldb will init in
## /data/ldb1/ldb/, /data/ldb2/ldb/. We can mount each disk to
## data/ldb1, data/ldb2, so we can init each instance on each disk.
data_dir=data/ldb
## leveldb instance count, buckets will be well-distributed to instances
ldb_db_instance_count=1
## whether load backup version when startup.
## backup version may be created to maintain some db data of specifid version.
ldb_load_backup_version=0
## whether support version strategy.
## if yes, put will do get operation to update existed items's meta info(version .etc),
## get unexist item is expensive for leveldb. set 0 to disable if nobody even care version stuff.
ldb_db_version_care=1
## time range to compact for gc, 1-1 means do no compaction at all
ldb_compact_gc_range = 3-6
## backgroud task check compact interval (s)
ldb_check_compact_interval = 120
## use cache count, 0 means NOT use cache,`ldb_use_cache_count should NOT be larger
## than `ldb_db_instance_count, and better to be a factor of `ldb_db_instance_count.
## each cache mdb's config depends on mdb's config item(mdb_type, slab_mem_size, etc)
ldb_use_cache_count=1
## cache stat can't report configserver, record stat locally, stat file size.
## file will be rotate when file size is over this.
ldb_cache_stat_file_size=20971520
## migrate item batch size one time (1M)
ldb_migrate_batch_size = 3145728
## migrate item batch count.
## real batch migrate items depends on the smaller size/count
ldb_migrate_batch_count = 5000
## comparator_type bitcmp by default
# ldb_comparator_type=numeric
## numeric comparator: special compare method for user_key sorting in order to reducing compact
## parameters for numeric compare. format: [meta][prefix][delimiter][number][suffix]
## skip meta size in compare
# ldb_userkey_skip_meta_size=2
## delimiter between prefix and number
# ldb_userkey_num_delimiter=:
####
## use blommfilter
ldb_use_bloomfilter=1
## use mmap to speed up random acess file(sstable),may cost much memory
ldb_use_mmap_random_access=0
## how many highest levels to limit compaction
ldb_limit_compact_level_count=0
## limit compaction ratio: allow doing one compaction every ldb_limit_compact_interval
## 0 means limit all compaction
ldb_limit_compact_count_interval=0
## limit compaction time interval
## 0 means limit all compaction
ldb_limit_compact_time_interval=0
## limit compaction time range, start == end means doing limit the whole day.
ldb_limit_compact_time_range=6-1
## limit delete obsolete files when finishing one compaction
ldb_limit_delete_obsolete_file_interval=5
## whether trigger compaction by seek
ldb_do_seek_compaction=0
## whether split mmt when compaction with user-define logic(bucket range, eg)
ldb_do_split_mmt_compaction=0

## do specify compact
## time range 24 hours
ldb_specify_compact_time_range=0-6
ldb_specify_compact_max_threshold=10000
## score threshold default = 1
ldb_specify_compact_score_threshold=1

#### following config effects on FastDump ####
## when ldb_db_instance_count > 1, bucket will be sharded to instance base on config strategy.
## current supported:
##  hash : just do integer hash to bucket number then module to instance, instance's balance may be
##         not perfect in small buckets set. same bucket will be sharded to same instance
##         all the time, so data will be reused even if buckets owned by server changed(maybe cluster has changed),
##  map  : handle to get better balance among all instances. same bucket may be sharded to different instance based
##         on different buckets set(data will be migrated among instances).
ldb_bucket_index_to_instance_strategy=map
## bucket index can be updated. this is useful if the cluster wouldn't change once started
## even server down/up accidently.
ldb_bucket_index_can_update=1
## strategy map will save bucket index statistics into file, this is the file's directory
ldb_bucket_index_file_dir=./data/bindex
## memory usage for memtable sharded by bucket when batch-put(especially for FastDump)
ldb_max_mem_usage_for_memtable=3221225472
####

#### leveldb config (Warning: you should know what you're doing.)
## one leveldb instance max open files(actually table_cache_ capacity, consider as working set, see `ldb_table_cache_size)
ldb_max_open_files=65535
## whether return fail when occure fail when init/load db, and
## if true, read data when compactiong will verify checksum
ldb_paranoid_check=0
## memtable size
ldb_write_buffer_size=67108864
## sstable size
ldb_target_file_size=8388608
## max file size in each level. level-n (n > 0): (n - 1) * 10 * ldb_base_level_size
ldb_base_level_size=134217728
## sstable's block size
# ldb_block_size=4096
## sstable cache size (override `ldb_max_open_files)
ldb_table_cache_size=1073741824
##block cache size
ldb_block_cache_size=16777216
## arena used by memtable, arena block size
#ldb_arenablock_size=4096
## key is prefix-compressed period in block,
## this is period length(how many keys will be prefix-compressed period)
# ldb_block_restart_interval=16
## specifid compression method (snappy only now)
# ldb_compression=1
## compact when sstables count in level-0 is over this trigger
ldb_l0_compaction_trigger=1
## whether limit write with l0's filecount, if false
ldb_l0_limit_write_with_count=0
## write will slow down when sstables count in level-0 is over this trigger
## or sstables' filesize in level-0 is over trigger * ldb_write_buffer_size if ldb_l0_limit_write_with_count=0
ldb_l0_slowdown_write_trigger=32
## write will stop(wait until trigger down)
ldb_l0_stop_write_trigger=64
## when write memtable, max level to below maybe
ldb_max_memcompact_level=3
## read verify checksum
ldb_read_verify_checksums=0
## write sync log. (one write will sync log once, expensive)
ldb_write_sync=0
## bits per key when use bloom filter
#ldb_bloomfilter_bits_per_key=10
## filter data base logarithm. filterbasesize=1<<ldb_filter_base_logarithm
#ldb_filter_base_logarithm=12

[extras]
######## RT-related ########
#rt_oplist=1,2
# Threashold of latency beyond which would let the request be dumped out.
rt_threshold=8000
# Enable RT Module at startup
rt_auto_enable=0
# How many requests would be subject to RT Module
rt_percent=100
# Interval to reset the latency statistics, by seconds
rt_reset_interval=10

######## HotKey-related ########
hotk_oplist=2
# Sample count
hotk_sample_max=50000
# Reap count
hotk_reap_max=32
# Whether to send client feedback response
hotk_need_feedback=0
# Whether to dump out packets, caches or hot keys
hotk_need_dump=0
# Whether to just Do Hot one round
hotk_one_shot=0
# Whether having hot key depends on: sigma >= (average * hotk_hot_factor)
hotk_hot_factor=0.8

在CentOS 7下,安装目录下的 tair.sh 启动脚本有一行代码(55行)需要修改

makefile
tmpfs_size=`df -m |grep tmpfs | awk '{print $2}'`
#这行改成下面这一行
tmpfs_size=`df -m |grep /dev/shm | awk '{print $2}'`

启动Tair实例

shell
# 需要跟参数
[root@test tair_bin]# ./tair.sh
usage: ./tair.sh {start_cs|stop_cs|start_ds|stop_ds|start_iv|stop_iv|start_px|start_px [SERVER_COUNT]|clean|log_debug2warn|log_warn2debug}
# start_ds启动数据节点
[root@test tair_bin]# ./tair.sh start_ds
mdb engine. tmpfs_size: 1024  safety_size: 524  slab_mem_size: 512
[root@test tair_bin]# ps -ef | grep tair
root      1983     1  1 08:51 pts/0    00:00:00 ./sbin/tair_server -f ./etc/dataserver.conf
root      2011  1626  0 08:51 pts/0    00:00:00 grep --color=auto tair
# start_ds启动config配置节点
[root@test tair_bin]# ./tair.sh start_cs
[root@test tair_bin]# ps -ef | grep tair
root      1983     1  1 08:51 pts/0    00:00:05 ./sbin/tair_server -f ./etc/dataserver.conf
root      2018     1  0 08:58 pts/0    00:00:00 ./sbin/tair_cfg_svr -f ./etc/configserver.conf
root      2034  1626  0 08:58 pts/0    00:00:00 grep --color=auto tair

使用自带客户端测试读写

shell
[root@test tair_bin]# ./sbin/tairclient -c 192.168.31.97:5198 -g group_test
TAIR> put name itheima
put: success
TAIR> get name
KEY: name, LEN: 7
 raw data: itheima, \69\74\68\65\69\6D\61
TAIR> remove name
remove: success.
TAIR> get name
get failed: data not exists.

停止tair服务

shell
# 停止数据节点
[root@test tair_bin]# ./tair.sh stop_ds
# 停止配置节点
[root@test tair_bin]# ./tair.sh stop_cs
[root@test tair_bin]# ps -ef | grep tair
root      2061  1626  0 09:02 pts/0    00:00:00 grep --color=auto tair